home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / net / ruserpass.c < prev    next >
C/C++ Source or Header  |  1989-05-18  |  17KB  |  855 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #if defined(LIBC_SCCS) && !defined(lint)
  14. static char sccsid[] = "@(#)ruserpass.c    5.4 (Berkeley) 3/7/88";
  15. #endif /* LIBC_SCCS and not lint */
  16.  
  17. #include <stdio.h>
  18. #include <utmp.h>
  19. #include <ctype.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <errno.h>
  23. #include <strings.h>
  24.  
  25. #if !defined(__STDC__) && !defined(const)
  26. #define const /**/
  27. #endif
  28.  
  29. extern char *malloc(), *index(), *getenv(), *getpass(), *getlogin();
  30. extern char *ttyname();
  31. extern void mkpwclear();
  32. static void renv();
  33. static void rnetrc();
  34. static int token();
  35. static void enblkclr();
  36. static void enblknot();
  37. static void nbssetkey();
  38. static void blkencrypt();
  39. static struct utmp *getutmp();
  40. static char *renvlook();
  41. static char *deblknot(), *deblkclr();
  42. static char *nbs8decrypt(), *nbs8encrypt();
  43.  
  44. static    FILE *cfile;
  45. static char E[48];
  46.  
  47. void
  48. ruserpass(host, aname, apass)
  49.     char *host, **aname, **apass;
  50. {
  51.  
  52.     renv(host, aname, apass);
  53.     if (*aname == 0 || *apass == 0)
  54.         rnetrc(host, aname, apass);
  55.     if (*aname == 0) {
  56.         char *myname = getlogin();
  57.         *aname = malloc(16);
  58.         printf("Name (%s:%s): ", host, myname);
  59.         fflush(stdout);
  60.         if (read(2, *aname, 16) <= 0)
  61.             exit(1);
  62.         if ((*aname)[0] == '\n')
  63.             *aname = myname;
  64.         else
  65.             if (index(*aname, '\n'))
  66.                 *index(*aname, '\n') = 0;
  67.     }
  68.     if (*aname && *apass == 0) {
  69.         printf("Password (%s:%s): ", host, *aname);
  70.         fflush(stdout);
  71.         *apass = getpass("");
  72.     }
  73.     return;
  74. }
  75.  
  76. static void
  77. renv(host, aname, apass)
  78.     char *host, **aname, **apass;
  79. {
  80.     register char *cp;
  81.     char *comma;
  82.  
  83.     cp = renvlook(host);
  84.     if (cp == NULL)
  85.         return;
  86.     if (!isalpha(cp[0]))
  87.         return;
  88.     comma = index(cp, ',');
  89.     if (comma == 0)
  90.         return;
  91.     if (*aname == 0) {
  92.         *aname = malloc((unsigned) (comma - cp + 1));
  93.         strncpy(*aname, cp, comma - cp);
  94.     } else
  95.         if (strncmp(*aname, cp, comma - cp))
  96.             return;
  97.     comma++;
  98.     cp = malloc((unsigned) (strlen(comma)+1));
  99.     strcpy(cp, comma);
  100.     *apass = malloc(16);
  101.     mkpwclear(cp, host[0], *apass);
  102.     return;
  103. }
  104.  
  105. static char *
  106. renvlook(host)
  107.     char *host;
  108. {
  109.     register char *cp, **env;
  110.     extern char **environ;
  111.  
  112.     env = environ;
  113.     for (env = environ; *env != NULL; env++)
  114.         if (!strncmp(*env, "MACH", 4)) {
  115.             cp = index(*env, '=');
  116.             if (cp == 0)
  117.                 continue;
  118.             if (strncmp(*env+4, host, cp-(*env+4)))
  119.                 continue;
  120.             return (cp+1);
  121.         }
  122.     return (NULL);
  123. }
  124.  
  125. #define    DEFAULT    1
  126. #define    LOGIN    2
  127. #define    PASSWD    3
  128. #define    NOTIFY    4
  129. #define    WRITE    5
  130. #define    YES    6
  131. #define    NO    7
  132. #define    COMMAND    8
  133. #define    FORCE    9
  134. #define    ID    10
  135. #define    MACHINE    11
  136.  
  137. static char tokval[100];
  138.  
  139. static struct toktab {
  140.     char *tokstr;
  141.     int tval;
  142. } toktab[]= {
  143.     "default",    DEFAULT,
  144.     "login",    LOGIN,
  145.     "password",    PASSWD,
  146.     "notify",    NOTIFY,
  147.     "write",    WRITE,
  148.     "yes",        YES,
  149.     "y",        YES,
  150.     "no",        NO,
  151.     "n",        NO,
  152.     "command",    COMMAND,
  153.     "force",    FORCE,
  154.     "machine",    MACHINE,
  155.     0,        0
  156. };
  157.  
  158. static void
  159. rnetrc(host, aname, apass)
  160.     char *host, **aname, **apass;
  161. {
  162.     char *hdir, buf[BUFSIZ];
  163.     int t;
  164.     struct stat stb;
  165.     extern int errno;
  166.  
  167.     hdir = getenv("HOME");
  168.     if (hdir == NULL)
  169.         hdir = ".";
  170.     (void)sprintf(buf, "%s/.netrc", hdir);
  171.     cfile = fopen(buf, "r");
  172.     if (cfile == NULL) {
  173.         if (errno != ENOENT)
  174.             perror(buf);
  175.         return;
  176.     }
  177. next:
  178.     while ((t = token())) switch(t) {
  179.  
  180.     case DEFAULT:
  181.         (void) token();
  182.         continue;
  183.  
  184.     case MACHINE:
  185.         if (token() != ID || strcmp(host, tokval))
  186.             continue;
  187.         while ((t = token()) && t != MACHINE) switch(t) {
  188.  
  189.         case LOGIN:
  190.             if (token())
  191.                 if (*aname == 0) { 
  192.                     *aname = malloc((unsigned)
  193.                         (strlen(tokval) + 1));
  194.                     strcpy(*aname, tokval);
  195.                 } else {
  196.                     if (strcmp(*aname, tokval))
  197.                         goto next;
  198.                 }
  199.             break;
  200.         case PASSWD:
  201.             if (fstat(fileno(cfile), &stb) >= 0
  202.                 && (stb.st_mode & 077) != 0) {
  203.     fprintf(stderr, "Error - .netrc file not correct mode.\n");
  204.     fprintf(stderr, "Remove password or correct mode.\n");
  205.                 exit(1);
  206.             }
  207.             if (token() && *apass == 0) {
  208.                 *apass = malloc((unsigned)
  209.                     (strlen(tokval) + 1));
  210.                 strcpy(*apass, tokval);
  211.             }
  212.             break;
  213.         case COMMAND:
  214.         case NOTIFY:
  215.         case WRITE:
  216.         case FORCE:
  217.             (void) token();
  218.             break;
  219.         default:
  220.     fprintf(stderr, "Unknown .netrc option %s\n", tokval);
  221.             break;
  222.         }
  223.         goto done;
  224.     }
  225. done:
  226.     fclose(cfile);
  227. }
  228.  
  229. static int
  230. token()
  231. {
  232.     char *cp;
  233.     int c;
  234.     struct toktab *t;
  235.  
  236.     if (feof(cfile))
  237.         return (0);
  238.     while ((c = getc(cfile)) != EOF &&
  239.         (c == '\n' || c == '\t' || c == ' ' || c == ','))
  240.         continue;
  241.     if (c == EOF)
  242.         return (0);
  243.     cp = tokval;
  244.     if (c == '"') {
  245.         while ((c = getc(cfile)) != EOF && c != '"') {
  246.             if (c == '\\')
  247.                 c = getc(cfile);
  248.             *cp++ = c;
  249.         }
  250.     } else {
  251.         *cp++ = c;
  252.         while ((c = getc(cfile)) != EOF
  253.             && c != '\n' && c != '\t' && c != ' ' && c != ',') {
  254.             if (c == '\\')
  255.                 c = getc(cfile);
  256.             *cp++ = c;
  257.         }
  258.     }
  259.     *cp = 0;
  260.     if (tokval[0] == 0)
  261.         return (0);
  262.     for (t = toktab; t->tokstr; t++)
  263.         if (!strcmp(t->tokstr, tokval))
  264.             return (t->tval);
  265.     return (ID);
  266. }
  267. /* rest is nbs.c stolen from berknet */
  268.  
  269. /*
  270.  * The E bit-selection table.
  271.  */
  272. static char    e[] = {
  273.     32, 1, 2, 3, 4, 5,
  274.      4, 5, 6, 7, 8, 9,
  275.      8, 9,10,11,12,13,
  276.     12,13,14,15,16,17,
  277.     16,17,18,19,20,21,
  278.     20,21,22,23,24,25,
  279.     24,25,26,27,28,29,
  280.     28,29,30,31,32, 1,
  281. };
  282.  
  283. static char *
  284. nbsencrypt(str,key,result)
  285.   char *result;
  286.   char *str, *key;
  287. {
  288.     static char buf[20],oldbuf[20];
  289.     register int j;
  290.     result[0] = 0;
  291.     strcpy(oldbuf,key);
  292.     while(*str){
  293.         for(j=0;j<10;j++)buf[j] = 0;
  294.         for(j=0;j<8 && *str;j++)buf[j] = *str++;
  295.         strcat(result,nbs8encrypt(buf,oldbuf));
  296.         strcat(result,"$");
  297.         strcpy(oldbuf,buf);
  298.         }
  299.     return(result);
  300. }
  301.  
  302. static char *
  303. nbsdecrypt(cpt,key,result)
  304.   char *result;
  305.   char *cpt,*key;
  306. {
  307.     char *s;
  308.     char c,oldbuf[20];
  309.     result[0] = 0;
  310.     strcpy(oldbuf,key);
  311.     while(*cpt){
  312.         for(s = cpt;*s && *s != '$';s++);
  313.         c = *s;
  314.         *s = 0;
  315.         strcpy(oldbuf,nbs8decrypt(cpt,oldbuf));
  316.         strcat(result,oldbuf);
  317.         if(c == 0)break;
  318.         cpt = s + 1;
  319.         }
  320.     return(result);
  321.     }
  322.  
  323. static char *
  324. nbs8encrypt(str,key)
  325.     char *str, *key;
  326. {
  327.     static char keyblk[100], blk[100];
  328.     register int i;
  329.  
  330.     enblkclr(keyblk,key);
  331.     nbssetkey(keyblk);
  332.  
  333.     for(i=0;i<48;i++) E[i] = e[i];
  334.     enblkclr(blk,str);
  335.     blkencrypt(blk,0);            /* forward dir */
  336.  
  337.     return(deblknot(blk));
  338. }
  339.  
  340. static char *
  341. nbs8decrypt(crp,key)
  342.     char *crp, *key;
  343. {
  344.     static char keyblk[100], blk[100];
  345.     register int i;
  346.  
  347.     enblkclr(keyblk,key);
  348.     nbssetkey(keyblk);
  349.  
  350.     for(i=0;i<48;i++) E[i] = e[i];
  351.     enblknot(blk,crp);
  352.     blkencrypt(blk,1);            /* backward dir */
  353.  
  354.     return(deblkclr(blk));
  355. }
  356.  
  357. static void
  358. enblkclr(blk,str)        /* ignores top bit of chars in string str */
  359. char *blk,*str;
  360. {
  361.     register int i,j;
  362.     char c;
  363.     for(i=0;i<70;i++)blk[i] = 0;
  364.     for(i=0; (c= *str) && i<64; str++){
  365.         for(j=0; j<7; j++, i++)
  366.         blk[i] = (c>>(6-j)) & 01;
  367.         i++;
  368.     }
  369.     return;
  370. }
  371.  
  372. static
  373. char *deblkclr(blk)
  374. char *blk; {
  375.     register int i,j;
  376.     char c;
  377.     static char iobuf[30];
  378.     for(i=0; i<10; i++){
  379.         c = 0;
  380.         for(j=0; j<7; j++){
  381.             c <<= 1;
  382.             c |= blk[8*i+j];
  383.             }
  384.         iobuf[i] = c;
  385.     }
  386.     iobuf[i] = 0;
  387.     return(iobuf);
  388.     }
  389.  
  390. static void
  391. enblknot(blk,crp)
  392.     char *blk;
  393.     char *crp;
  394. {
  395.     register int i,j;
  396.     char c;
  397.  
  398.     for(i=0;i<70;i++)blk[i] = 0;
  399.     for(i=0; (c= *crp) && i<64; crp++){
  400.         if(c>'Z') c -= 6;
  401.         if(c>'9') c -= 7;
  402.         c -= '.';
  403.         for(j=0; j<6; j++, i++)
  404.         blk[i] = (c>>(5-j)) & 01;
  405.     }
  406. }
  407.  
  408. static char *
  409. deblknot(blk)
  410.     char *blk;
  411. {
  412.     register int i,j;
  413.     char c;
  414.     static char iobuf[30];
  415.  
  416.     for(i=0; i<11; i++) {
  417.         c = 0;
  418.         for(j=0; j<6; j++){
  419.             c <<= 1;
  420.             c |= blk[6*i+j];
  421.             }
  422.         c += '.';
  423.         if(c > '9')c += 7;
  424.         if(c > 'Z')c += 6;
  425.         iobuf[i] = c;
  426.     }
  427.     iobuf[i] = 0;
  428.     return(iobuf);
  429. }
  430.  
  431. /*
  432.  * This program implements the
  433.  * Proposed Federal Information Processing
  434.  *  Data Encryption Standard.
  435.  * See Federal Register, March 17, 1975 (40FR12134)
  436.  */
  437.  
  438. /*
  439.  * Initial permutation,
  440.  */
  441. static    char    IP[] = {
  442.     58,50,42,34,26,18,10, 2,
  443.     60,52,44,36,28,20,12, 4,
  444.     62,54,46,38,30,22,14, 6,
  445.     64,56,48,40,32,24,16, 8,
  446.     57,49,41,33,25,17, 9, 1,
  447.     59,51,43,35,27,19,11, 3,
  448.     61,53,45,37,29,21,13, 5,
  449.     63,55,47,39,31,23,15, 7,
  450. };
  451.  
  452. /*
  453.  * Final permutation, FP = IP^(-1)
  454.  */
  455. static const char FP[] = {
  456.     40, 8,48,16,56,24,64,32,
  457.     39, 7,47,15,55,23,63,31,
  458.     38, 6,46,14,54,22,62,30,
  459.     37, 5,45,13,53,21,61,29,
  460.     36, 4,44,12,52,20,60,28,
  461.     35, 3,43,11,51,19,59,27,
  462.     34, 2,42,10,50,18,58,26,
  463.     33, 1,41, 9,49,17,57,25,
  464. };
  465.  
  466. /*
  467.  * Permuted-choice 1 from the key bits
  468.  * to yield C and D.
  469.  * Note that bits 8,16... are left out:
  470.  * They are intended for a parity check.
  471.  */
  472. static const char PC1_C[] = {
  473.     57,49,41,33,25,17, 9,
  474.      1,58,50,42,34,26,18,
  475.     10, 2,59,51,43,35,27,
  476.     19,11, 3,60,52,44,36,
  477. };
  478.  
  479. static const char PC1_D[] = {
  480.     63,55,47,39,31,23,15,
  481.      7,62,54,46,38,30,22,
  482.     14, 6,61,53,45,37,29,
  483.     21,13, 5,28,20,12, 4,
  484. };
  485.  
  486. /*
  487.  * Sequence of shifts used for the key schedule.
  488. */
  489. static const char shifts[] = {
  490.     1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,
  491. };
  492.  
  493. /*
  494.  * Permuted-choice 2, to pick out the bits from
  495.  * the CD array that generate the key schedule.
  496.  */
  497. static const char PC2_C[] = {
  498.     14,17,11,24, 1, 5,
  499.      3,28,15, 6,21,10,
  500.     23,19,12, 4,26, 8,
  501.     16, 7,27,20,13, 2,
  502. };
  503.  
  504. static const char PC2_D[] = {
  505.     41,52,31,37,47,55,
  506.     30,40,51,45,33,48,
  507.     44,49,39,56,34,53,
  508.     46,42,50,36,29,32,
  509. };
  510.  
  511. /*
  512.  * The C and D arrays used to calculate the key schedule.
  513.  */
  514.  
  515. static    char    C[28];
  516. static    char    D[28];
  517. /*
  518.  * The key schedule.
  519.  * Generated from the key.
  520.  */
  521. static char KS[16][48];
  522.  
  523. /*
  524.  * Set up the key schedule from the key.
  525.  */
  526.  
  527. static void
  528. nbssetkey(key)
  529.     char *key;
  530. {
  531.     register i, j, k;
  532.     int t;
  533.  
  534.     /*
  535.      * First, generate C and D by permuting
  536.      * the key.  The low order bit of each
  537.      * 8-bit char is not used, so C and D are only 28
  538.      * bits apiece.
  539.      */
  540.     for (i=0; i<28; i++) {
  541.         C[i] = key[PC1_C[i]-1];
  542.         D[i] = key[PC1_D[i]-1];
  543.     }
  544.     /*
  545.      * To generate Ki, rotate C and D according
  546.      * to schedule and pick up a permutation
  547.      * using PC2.
  548.      */
  549.     for (i=0; i<16; i++) {
  550.         /*
  551.          * rotate.
  552.          */
  553.         for (k=0; k<shifts[i]; k++) {
  554.             t = C[0];
  555.             for (j=0; j<28-1; j++)
  556.                 C[j] = C[j+1];
  557.             C[27] = t;
  558.             t = D[0];
  559.             for (j=0; j<28-1; j++)
  560.                 D[j] = D[j+1];
  561.             D[27] = t;
  562.         }
  563.         /*
  564.          * get Ki. Note C and D are concatenated.
  565.          */
  566.         for (j=0; j<24; j++) {
  567.             KS[i][j] = C[PC2_C[j]-1];
  568.             KS[i][j+24] = D[PC2_D[j]-28-1];
  569.         }
  570.     }
  571.     return;
  572. }
  573.  
  574.  
  575. /*
  576.  * The 8 selection functions.
  577.  * For some reason, they give a 0-origin
  578.  * index, unlike everything else.
  579.  */
  580. static const char S[8][64] = {
  581.     14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
  582.      0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
  583.      4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
  584.     15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
  585.  
  586.     15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
  587.      3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
  588.      0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
  589.     13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
  590.  
  591.     10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
  592.     13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
  593.     13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
  594.      1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
  595.  
  596.      7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
  597.     13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
  598.     10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
  599.      3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
  600.  
  601.      2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
  602.     14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
  603.      4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
  604.     11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
  605.  
  606.     12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
  607.     10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
  608.      9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
  609.      4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
  610.  
  611.      4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
  612.     13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
  613.      1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
  614.      6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
  615.  
  616.     13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
  617.      1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
  618.      7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
  619.      2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
  620. };
  621.  
  622. /*
  623.  * P is a permutation on the selected combination
  624.  * of the current L and key.
  625.  */
  626. static const char P[] = {
  627.     16, 7,20,21,
  628.     29,12,28,17,
  629.      1,15,23,26,
  630.      5,18,31,10,
  631.      2, 8,24,14,
  632.     32,27, 3, 9,
  633.     19,13,30, 6,
  634.     22,11, 4,25,
  635. };
  636.  
  637. /*
  638.  * The current block, divided into 2 halves.
  639.  */
  640. static char L[32], R[32];
  641. static char tempL[32];
  642. static char f[32];
  643.  
  644. /*
  645.  * The combination of the key and the input, before selection.
  646.  */
  647. static char preS[48];
  648.  
  649. /*
  650.  * The payoff: encrypt a block.
  651.  */
  652.  
  653. static void
  654. blkencrypt(block, edflag)
  655.     char *block;
  656. {
  657.     int i, ii;
  658.     register t, j, k;
  659.  
  660.     /*
  661.      * First, permute the bits in the input
  662.      */
  663.     for (j=0; j<64; j++)
  664.         L[j] = block[IP[j]-1];
  665.     /*
  666.      * Perform an encryption operation 16 times.
  667.      */
  668.     for (ii=0; ii<16; ii++) {
  669.         /*
  670.          * Set direction
  671.          */
  672.         if (edflag)
  673.             i = 15-ii;
  674.         else
  675.             i = ii;
  676.         /*
  677.          * Save the R array,
  678.          * which will be the new L.
  679.          */
  680.         for (j=0; j<32; j++)
  681.             tempL[j] = R[j];
  682.         /*
  683.          * Expand R to 48 bits using the E selector;
  684.          * exclusive-or with the current key bits.
  685.          */
  686.         for (j=0; j<48; j++)
  687.             preS[j] = R[E[j]-1] ^ KS[i][j];
  688.         /*
  689.          * The pre-select bits are now considered
  690.          * in 8 groups of 6 bits each.
  691.          * The 8 selection functions map these
  692.          * 6-bit quantities into 4-bit quantities
  693.          * and the results permuted
  694.          * to make an f(R, K).
  695.          * The indexing into the selection functions
  696.          * is peculiar; it could be simplified by
  697.          * rewriting the tables.
  698.          */
  699.         for (j=0; j<8; j++) {
  700.             t = 6*j;
  701.             k = S[j][(preS[t+0]<<5)+
  702.                 (preS[t+1]<<3)+
  703.                 (preS[t+2]<<2)+
  704.                 (preS[t+3]<<1)+
  705.                 (preS[t+4]<<0)+
  706.                 (preS[t+5]<<4)];
  707.             t = 4*j;
  708.             f[t+0] = (k>>3)&01;
  709.             f[t+1] = (k>>2)&01;
  710.             f[t+2] = (k>>1)&01;
  711.             f[t+3] = (k>>0)&01;
  712.         }
  713.         /*
  714.          * The new R is L ^ f(R, K).
  715.          * The f here has to be permuted first, though.
  716.          */
  717.         for (j=0; j<32; j++)
  718.             R[j] = L[j] ^ f[P[j]-1];
  719.         /*
  720.          * Finally, the new L (the original R)
  721.          * is copied back.
  722.          */
  723.         for (j=0; j<32; j++)
  724.             L[j] = tempL[j];
  725.     }
  726.     /*
  727.      * The output L and R are reversed.
  728.      */
  729.     for (j=0; j<32; j++) {
  730.         t = L[j];
  731.         L[j] = R[j];
  732.         R[j] = t;
  733.     }
  734.     /*
  735.      * The final output
  736.      * gets the inverse permutation of the very original.
  737.      */
  738.     for (j=0; j<64; j++)
  739.         block[j] = L[FP[j]-1];
  740.     return;
  741. }
  742. /*
  743.     getutmp()
  744.     return a pointer to the system utmp structure associated with
  745.     terminal sttyname, e.g. "/dev/tty3"
  746.     Is version independent-- will work on v6 systems
  747.     return NULL if error
  748. */
  749.  
  750. static struct utmp *
  751. getutmp(sttyname)
  752.     char *sttyname;
  753. {
  754.     static struct utmp utmpstr;
  755.     FILE *fdutmp;
  756.  
  757.     if(sttyname == NULL || sttyname[0] == 0)return(NULL);
  758.  
  759.     fdutmp = fopen("/etc/utmp","r");
  760.     if(fdutmp == NULL)return(NULL);
  761.  
  762.     while(fread((char *) &utmpstr, 1, sizeof utmpstr, fdutmp)
  763.         == sizeof utmpstr)
  764.         if(strcmp(utmpstr.ut_line,sttyname+5) == 0){
  765.             fclose(fdutmp);
  766.             return(&utmpstr);
  767.         }
  768.     fclose(fdutmp);
  769.     return(NULL);
  770. }
  771.  
  772. static void
  773. sreverse(sto, sfrom)
  774.     register char *sto, *sfrom;
  775. {
  776.     register int i;
  777.  
  778.     i = strlen(sfrom);
  779.     while (i >= 0)
  780.         *sto++ = sfrom[i--];
  781.     return;
  782. }
  783.  
  784. static char *
  785. mkenvkey(mch)
  786.     char mch;
  787. {
  788.     static char skey[40];
  789.     register struct utmp *putmp;
  790.     char stemp[40], stemp1[40], sttyname[30];
  791.     register char *sk,*p;
  792.  
  793.     if (isatty(2))
  794.         strcpy(sttyname,ttyname(2));
  795.     else if (isatty(0))
  796.         strcpy(sttyname,ttyname(0));
  797.     else if (isatty(1))
  798.         strcpy(sttyname,ttyname(1));
  799.     else
  800.         return (NULL);
  801.     putmp = getutmp(sttyname);
  802.     if (putmp == NULL)
  803.         return (NULL);
  804.     sk = skey;
  805.     p = putmp->ut_line;
  806.     while (*p)
  807.         *sk++ = *p++;
  808.     *sk++ = mch;
  809.     (void)sprintf(stemp, "%ld", putmp->ut_time);
  810.     sreverse(stemp1, stemp);
  811.     p = stemp1;
  812.     while (*p)
  813.         *sk++ = *p++;
  814.     *sk = 0;
  815.     return (skey);
  816. }
  817.  
  818. void
  819. mkpwunclear(spasswd,mch,sencpasswd)
  820.     char mch, *spasswd, *sencpasswd;
  821. {
  822.     register char *skey;
  823.  
  824.     if (spasswd[0] == 0) {
  825.         sencpasswd[0] = 0;
  826.         return;
  827.     }
  828.     skey = mkenvkey(mch);
  829.     if (skey == NULL) {
  830.         fprintf(stderr, "Can't make key\n");
  831.         exit(1);
  832.     }
  833.     (void) nbsencrypt(spasswd, skey, sencpasswd);
  834.     return;
  835. }
  836.  
  837. void
  838. mkpwclear(sencpasswd,mch,spasswd)
  839.     char mch, *spasswd, *sencpasswd;
  840. {
  841.     register char *skey;
  842.  
  843.     if (sencpasswd[0] == 0) {
  844.         spasswd[0] = 0;
  845.         return;
  846.     }
  847.     skey = mkenvkey(mch);
  848.     if (skey == NULL) {
  849.         fprintf(stderr, "Can't make key\n");
  850.         exit(1);
  851.     }
  852.     (void) nbsdecrypt(sencpasswd, skey, spasswd);
  853.     return;
  854. }
  855.